﻿using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using HtmlAgilityPack;
using ImoviesBlazorAntPro.Server.Helpers;
using ImoviesBlazorAntPro.Server.Repository;
using ImoviesBlazorAntPro.Shared.Entities;
using ImoviesBlazorAntPro.Shared;

namespace ImoviesBlazorAntPro.Server.Controllers
{
    /// <summary>
    /// 视频采集控制器
    /// </summary>
    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class CollectController : ControllerBase
    {
        private readonly ITeleplayRepository _teleplayRepository;
        private readonly IMovieRepository _movieRepository;
        private readonly IAnimationRepository _animationRepository;
        private readonly ITeleplayVlinkRepository _teleplayVlinkRepository;
        private readonly IMovieVlinkRepository _movieVlinkRepository;
        private readonly IAnimationVlinkRepository _animationVlinkRepository;

        public CollectController(ITeleplayRepository teleplayRepository,
            IMovieRepository movieRepository,
            IAnimationRepository animationRepository,
            ITeleplayVlinkRepository teleplayVlinkRepository,
            IMovieVlinkRepository movieVlinkRepository,
            IAnimationVlinkRepository animationVlinkRepository)
        {
            this._teleplayRepository = teleplayRepository;
            this._movieRepository = movieRepository;
            this._animationRepository = animationRepository;
            this._teleplayVlinkRepository = teleplayVlinkRepository;
            this._movieVlinkRepository = movieVlinkRepository;
            this._animationVlinkRepository = animationVlinkRepository;
        }

        /// <summary>
        /// 电视剧采集任务
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private async Task TeleplayCollectTask(string url)
        {
            string html = await HtmlUtils.GetHtmlTxt(url);

            if (string.IsNullOrEmpty(html)) return;
            try
            {
                var video = doCollect(html);
                var videoInfo = video.Item1;
                videoInfo.Url = url;
                _teleplayRepository.AddTeleplay(new Teleplay(videoInfo.Id, videoInfo.Name,
                                            videoInfo.Url, videoInfo.Category,
                                            videoInfo.Region, videoInfo.Year,
                                            videoInfo.Actors, videoInfo.Director,
                                            videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

                var links = video.Item2;
                var vlinks = links.Select(x => new TeleplayVlink(videoInfo.Id, x.Key, x.Value));
                await _teleplayVlinkRepository.BatchAddTeleplayVlink(vlinks);

                _teleplayRepository.Save();
                await _teleplayVlinkRepository.SaveAsync();
            }
            catch
            {
                return;
            }
        }

        /// <summary>
        /// 电视剧采集
        /// </summary>
        /// <param name="urls">url列表</param>
        /// <returns></returns>
        [HttpPost("teleplay")]
        public async Task<ActionResult> TeleplayCollect([FromBody] List<string> urls)
        {
            List<Task> tasks = new List<Task>();
            foreach (string url in urls)
            {
                var task = Task.Run(async () => await TeleplayCollectTask(url));
                tasks.Add(task);
                await Task.Delay(300);
            }
            Task.WaitAll(tasks.ToArray());

            //foreach (string url in urls)
            //{
            //    string html = await HtmlUtils.GetHtmlTxt(url);

            //    if (string.IsNullOrEmpty(html)) return Ok();

            //    try
            //    {
            //        var video = doCollect(html);
            //        var videoInfo = video.Item1;
            //        videoInfo.Url = url;
            //        _teleplayRepository.AddTeleplay(new Teleplay(videoInfo.Id, videoInfo.Name,
            //                                    videoInfo.Url, videoInfo.Category,
            //                                    videoInfo.Region, videoInfo.Year,
            //                                    videoInfo.Actors, videoInfo.Director,
            //                                    videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

            //        var links = video.Item2;
            //        var vlinks = links.Select(x => new TeleplayVlink(videoInfo.Id, x.Key, x.Value));
            //        await _teleplayVlinkRepository.BatchAddTeleplayVlink(vlinks);

            //        _teleplayRepository.Save();
            //        await _teleplayVlinkRepository.SaveAsync();
            //    }
            //    catch
            //    {
            //        continue;
            //    }

            //    await Task.Delay(100);
            //}
            return Ok();
        }


        /// <summary>
        /// 电影采集任务
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private async Task MovieCollectTask(string url)
        {
            string html = await HtmlUtils.GetHtmlTxt(url);
            if (string.IsNullOrEmpty(html)) return;

            try
            {
                var video = doCollect(html);
                var videoInfo = video.Item1;
                videoInfo.Url = url;
                _movieRepository.AddMovie(new Movie(videoInfo.Id, videoInfo.Name,
                                            videoInfo.Url, videoInfo.Category,
                                            videoInfo.Region, videoInfo.Year,
                                            videoInfo.Actors, videoInfo.Director,
                                            videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

                var links = video.Item2;
                var vlinks = links.Select(x => new MovieVlink(videoInfo.Id, x.Key, x.Value));
                await _movieVlinkRepository.BatchAddMovieVlink(vlinks);

                _movieRepository.Save();
                await _movieVlinkRepository.SaveAsync();
            }
            catch
            {
                return;
            }
        }

        /// <summary>
        /// 电影采集
        /// </summary>
        /// <param name="urls">url列表</param>
        /// <returns></returns>
        [HttpPost("movie")]
        public async Task<ActionResult> MovieCollect([FromBody] List<string> urls)
        {
            List<Task> tasks = new List<Task>();
            foreach (string url in urls)
            {
                var task = Task.Run(async () => await MovieCollectTask(url));
                tasks.Add(task);
                await Task.Delay(300);
            }
            Task.WaitAll(tasks.ToArray());

            //foreach (string url in urls)
            //{
            //    string html = await HtmlUtils.GetHtmlTxt(url);
            //    if (string.IsNullOrEmpty(html)) return Ok();

            //    try
            //    {
            //        var video = doCollect(html);
            //        var videoInfo = video.Item1;
            //        videoInfo.Url = url;
            //        _movieRepository.AddMovie(new Movie(videoInfo.Id, videoInfo.Name,
            //                                    videoInfo.Url, videoInfo.Category,
            //                                    videoInfo.Region, videoInfo.Year,
            //                                    videoInfo.Actors, videoInfo.Director,
            //                                    videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

            //        var links = video.Item2;
            //        var vlinks = links.Select(x => new MovieVlink(videoInfo.Id, x.Key, x.Value));
            //        await _movieVlinkRepository.BatchAddMovieVlink(vlinks);

            //        _movieRepository.Save();
            //        await _movieVlinkRepository.SaveAsync();
            //    }
            //    catch
            //    {
            //        continue;
            //    }

            //    await Task.Delay(100);
            //}
            return Ok();
        }


        /// <summary>
        /// 动漫采集任务
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private async Task AnimationCollectTask(string url)
        {
            string html = await HtmlUtils.GetHtmlTxt(url);
            if (string.IsNullOrEmpty(html)) return;

            try
            {
                var video = doCollect(html);
                var videoInfo = video.Item1;
                videoInfo.Url = url;
                _animationRepository.AddAnimation(new Animation(videoInfo.Id, videoInfo.Name,
                                            videoInfo.Url, videoInfo.Category,
                                            videoInfo.Region, videoInfo.Year,
                                            videoInfo.Actors, videoInfo.Director,
                                            videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

                var links = video.Item2;
                var vlinks = links.Select(x => new AnimationVlink(videoInfo.Id, x.Key, x.Value));
                await _animationVlinkRepository.BatchAddMovieVlink(vlinks);

                _animationRepository.Save();
                await _animationVlinkRepository.SaveAsync();
            }
            catch
            {
                return;
            }
        }


        /// <summary>
        /// 动漫采集
        /// </summary>
        /// <param name="urls">url列表</param>
        /// <returns></returns>
        [HttpPost("animation")]
        public async Task<ActionResult> AnimationCollect([FromBody] List<string> urls)
        {
            List<Task> tasks = new List<Task>();
            foreach (string url in urls)
            {
                var task = Task.Run(async () => await AnimationCollectTask(url));
                tasks.Add(task);
                await Task.Delay(300);
            }
            Task.WaitAll(tasks.ToArray());

            //foreach (string url in urls)
            //{
            //    string html = await HtmlUtils.GetHtmlTxt(url);
            //    if (string.IsNullOrEmpty(html)) return Ok();

            //    try
            //    {
            //        var video = doCollect(html);
            //        var videoInfo = video.Item1;
            //        videoInfo.Url = url;
            //        _animationRepository.AddAnimation(new Animation(videoInfo.Id, videoInfo.Name,
            //                                    videoInfo.Url, videoInfo.Category,
            //                                    videoInfo.Region, videoInfo.Year,
            //                                    videoInfo.Actors, videoInfo.Director,
            //                                    videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

            //        var links = video.Item2;
            //        var vlinks = links.Select(x => new AnimationVlink(videoInfo.Id, x.Key, x.Value));
            //        await _animationVlinkRepository.BatchAddMovieVlink(vlinks);

            //        _animationRepository.Save();
            //        await _animationVlinkRepository.SaveAsync();
            //    }
            //    catch
            //    {
            //        continue;
            //    }

            //    await Task.Delay(100);
            //}
            return Ok();
        }

        /// <summary>
        /// 视频信息采集函数
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        private Tuple<VideoInfo, Dictionary<string, string>> doCollect(string html)
        {
            VideoInfo info = new VideoInfo();

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html);

            // name
            HtmlNode nameNode = doc.DocumentNode.SelectSingleNode("/html/body/div/div[3]/div/div[1]/div[1]/div[2]/div[1]/h1");
            string name = nameNode?.InnerHtml ?? "";
            info.Name = name;
            // id
            byte[] bytes = MD5.HashData(Encoding.UTF8.GetBytes(name));
            info.Id = BitConverter.ToString(bytes)?.Replace("-", "");
            // img
            HtmlNode imgNode = doc.DocumentNode.SelectSingleNode("/html/body/div/div[3]/div/div[1]/div[1]/div[1]/div/div/img");
            string img = imgNode?.GetAttributeValue("data-original", "");
            info.Img = img;
            // year
            HtmlNode yearNode = doc.DocumentNode.SelectSingleNode("/html/body/div/div[3]/div/div[1]/div[1]/div[2]/div[1]/div[1]/div[1]/a");
            string tmp = yearNode?.InnerHtml;
            uint year = string.IsNullOrEmpty(tmp) ? 0 : uint.Parse(tmp);
            info.Year = year;
            // region
            HtmlNode regionNode = doc.DocumentNode.SelectSingleNode("/html/body/div/div[3]/div/div[1]/div[1]/div[2]/div[1]/div[1]/div[2]/a");
            string region = regionNode?.InnerHtml;
            info.Region = region;
            // cate
            string cate = "";
            HtmlNode cateNode = doc.DocumentNode.SelectSingleNode("/html/body/div/div[3]/div/div[1]/div[1]/div[2]/div[1]/div[1]/div[3]");
            foreach (var n in cateNode?.ChildNodes)
            {
                cate += n.InnerText;
            }
            cate = cate.Replace(@"\n", "");
            info.Category = cate;
            // intro
            HtmlNode introNode = doc.DocumentNode.SelectSingleNode("/html/body/div/div[3]/div/div[1]/div[1]/div[2]/div[2]/div[1]/div[1]/div/p");
            string intro = introNode?.InnerHtml;
            info.Intro = intro.Trim();
            // director
            HtmlNode directorNode = doc.DocumentNode.SelectSingleNode("/html/body/div/div[3]/div/div[1]/div[1]/div[2]/div[2]/div[1]/div[2]/div");
            string director = "";
            foreach (var n in directorNode?.ChildNodes)
            {
                director += n.InnerText;
            }
            director = director.Replace(@"\n", "");
            info.Director = director;
            // actors
            string actors = "";
            HtmlNode actorsNode = doc.DocumentNode.SelectSingleNode("/html/body/div/div[3]/div/div[1]/div[1]/div[2]/div[2]/div[1]/div[4]/div");
            foreach (HtmlNode n in actorsNode.ChildNodes)
            {
                actors += n.InnerHtml;
            }
            actors = actors.Replace(@"\n", "");
            info.Actors = actors;

            // links
            /// OK无广 html/body/div/div[3]/div/div[2]/div[2]/div/div
            HtmlNodeCollection linksNodes = doc.DocumentNode.SelectNodes("/html/body/div/div[3]/div/div[2]/div[2]/div/div/a");
            if (linksNodes == null)
            {
                linksNodes = doc.DocumentNode.SelectNodes("/html/body/div/div[3]/div/div[2]/div[3]/div/div/a");
            }
            if (linksNodes == null)
            {
                linksNodes = doc.DocumentNode.SelectNodes("/html/body/div/div[3]/div/div[2]/div[4]/div/div/a");
            }

            Dictionary<string, string> links = new Dictionary<string, string>();
            if (linksNodes != null)
            {
                foreach (var link in linksNodes)
                {
                    string linkUrl = $"https://www.freeok.vip{link?.GetAttributeValue("href", "")}";
                    string linkTitle = link?.GetAttributeValue("title", "");
                    if (linkTitle.StartsWith("播放"))
                    {
                        linkTitle = linkTitle.Substring(2);
                    }
                    links.Add(linkTitle, linkUrl);
                }
            }

            return Tuple.Create(info, links);
        }
    }
}
